package ldh.im.fxbase.service;

import ldh.im.fxbase.util.ThreadPoolUtil;

import javax.sound.sampled.*;
import java.io.*;
import java.util.function.Consumer;

public class AudioCommonService extends AudioService {

    private static final AudioFormat.Encoding AUDIO_ENCODE = AudioFormat.Encoding.PCM_SIGNED;

    public AudioCommonService(String saveDir) {
        this.saveDir = saveDir;
        initDir();
    }

    public AudioCommonService(String saveDir, int recordTotalTime) {
        this.saveDir = saveDir;
        this.recordTotalTime = recordTotalTime;
        initDir();
    }

    @Override
    public AudioFormat getAudioFormat() {
        float sampleRate = 8000;     // 8000,11025,16000,22050,44100
        int sampleSizeInBits = 16;    // 8,16
        int channels = 1;             // 1,2
        int frameSize = 2;
        boolean signed = true;        // true,false
        boolean bigEndian = false;    // true,false
        return new AudioFormat(AUDIO_ENCODE, sampleRate, sampleSizeInBits, channels, frameSize, sampleRate,  bigEndian);
    }

    @Override
    public void playRecord(String file, Consumer<Void> consumer) {
        ThreadPoolUtil.submit(()->{
            try(AudioInputStream ais = AudioSystem.getAudioInputStream(new File(file));
                Clip clip = AudioSystem.getClip()) {
                clip.open(ais);
                FloatControl gain = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                gain.setValue(gain.getMaximum());
                clip.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    @Override
    public Runnable getAudioRecordThread() {
        AudioFileFormat.Type fileType = AudioFileFormat.Type.WAVE;
        audioFile = saveDir + File.separator + getFileName() + "." + getFileType(fileType);
        String ff = audioFile;
        return () -> {
            File audioFile = new File(ff);

            ByteArrayInputStream bais = null;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            AudioInputStream ais = null;
            long startTime = System.currentTimeMillis();
            long time = 0;
            try {
                targetDataLine.open(audioFormat);
                targetDataLine.start();
                byte[] fragment = new byte[1024];

                ais = new AudioInputStream(targetDataLine);
                while (flag && time <= recordTotalTime * 1000) {
                    int length = targetDataLine.read(fragment, 0, fragment.length);
//                    fragment = AudioUtil.removeNoise(fragment, length);
                    baos.write(fragment, 0, length);
                    time = System.currentTimeMillis() - startTime;
                    changeTime(time);
                }

                //取得录音输入流
                audioFormat = getAudioFormat();
                byte audioData[] = baos.toByteArray();
                bais = new ByteArrayInputStream(audioData);
                ais = new AudioInputStream(bais, audioFormat, audioData.length / audioFormat.getFrameSize());
                AudioSystem.write(ais, fileType, audioFile);
                stopRecord();
                System.out.println("record time:" + time/100);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                close(bais, baos, ais);
            }
        };
    }

    //关闭流
    private void close(ByteArrayInputStream bais, ByteArrayOutputStream baos, AudioInputStream ais) {
        try {
            ais.close();
            bais.close();
            baos.reset();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getFileType(AudioFileFormat.Type fileType) {
        if (fileType == AudioFileFormat.Type.WAVE) {
            return "wav";
        }
        return "wav";
    }
}

